import React from 'react';
import { findDOMNode } from 'react-dom';
import cx from 'classnames';
import style from './style.objective-relative-bird-view';
import util from '../../util';
import { Progress, Avatar, Link, Button, Loading } from 'sq-ui';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux'
import * as okrAction from '../../actions/okr.action'
import { Motion, spring } from 'react-motion';
import sliceArray from 'sliceArray';
import moment from 'moment';
import {nav, active as navActive} from './style.objective-relative-tree-view';
import { Card } from './ObjectiveRelativeTreeView';
import _ from 'lodash';

export default
@connect(({ okr }) => ({ okr }), dispatch => ({actions: bindActionCreators({...okrAction }, dispatch)}))
class ObjectiveRelativeBirdView extends React.Component {

  state = {
    loadObjective: this.props.params.objectiveId,
    rootObjective: null,
  };

  static contextTypes = {
    router: React.PropTypes.object
  }

  reset() {
    this.props.actions.resetOkr();
    const s = this.state;
    for(var i in s) {
      s[i] = null;
    }

    this.setState({
      ...s,
    });

    Object.keys(util.bus._callbacks).forEach(name => {
      if (~name.indexOf('$objective_bird')) {
        util.bus.off(name.slice(1));
      }
    });
  }

  fetchRootObjective(objectiveId) {
    this.props.actions.fetchSingleObjective(objectiveId, res => {
      this.setState({
        rootObjective: res.data,
      });
    });
  }

  fetchContent(props) {
    const { objectiveId } = (props || this.props).params;
    this.props.actions.fetchObjectiveBirdView(objectiveId);
  }

  componentWillReceiveProps(props) {
    if (this.props.params.objectiveId != props.params.objectiveId) {
      this.reset();
      this.setState({
        loadObjective: props.params.objectiveId,
      });
      this.fetchContent(props);
      this.props.actions.fetchObjectiveDetail(props.params.objectiveId);
    }

    if (util.isNull(this.props.okr.birdView) && !util.isNull(props.okr.birdView)) {
      this.fetchRootObjective(_.find(_.flatten(props.okr.birdView), item => !item.hasParent).objectiveId);
    }
  }

  componentDidMount() {
    this.props.actions.resetObjectiveDetail();
    this.fetchContent();
    this.props.actions.fetchObjectiveDetail(this.props.params.objectiveId);
  }

  componentWillUnmount() {
    this.unmount = true;
    this.props.actions.resetOkr();
    Object.keys(util.bus._callbacks).forEach(name => {
      if (~name.indexOf('$objective_bird')) {
        util.bus.off(name.slice(1));
      }
    });
  }

  getRect(el) {
    return el.getBoundingClientRect();
  }

  getAngle(value) {
    return value < 0 ? 180 + value : value;
  }

  loadObjective(objectiveId) {
    this.setState({
      loadObjective: objectiveId,
    });

    const { detail } = this.props.okr;
    if (detail === null || detail.objectiveId != objectiveId) {
      this.props.actions.fetchObjectiveDetail(objectiveId);
    }
  }

  cancelObjective() {
    this.setState({
      loadObjective: null,
    });
    this.props.actions.resetObjectiveDetail();
  }

  drawLine(fromRect, toRect, objectiveId) {
    const { left: fromX, top: fromY } = fromRect;
    const { left: toX, top: toY } = toRect;

    //console.log(`Line: (${fromX}, ${fromY}) => (${toX}, ${toY}), 长度: ${Math.round(Math.sqrt(Math.pow((fromX - toX), 2) + Math.pow((fromY - toY), 2)))}, 位置: ${fromX < toX ? '右' : '左'}, 角度: ${this.getAngle(Math.atan((toY - fromY) / (toX - fromX)) * 180 / Math.PI)}, objective: ${objectiveId}`);

   setTimeout(() => {
     if (this.unmount) return;
     const arr = this.state[objectiveId] || [];
     this.setState({
       [objectiveId]: [
         ...arr,
         {
           length: Math.round(Math.sqrt(Math.pow((fromX - toX), 2) + Math.pow((fromY - toY), 2))),
           angle: this.getAngle(Math.atan((toY - fromY) / (toX - fromX)) * 180 / Math.PI),
         }
       ],
     });
   }, 0);

  }

  renderView() {
    const { birdView, detail } = this.props.okr;
    if (util.isNull(birdView)) return null;

    return (
      <div
        className={style.view}
      >
        {
          birdView.map((g, _i) => (
            <div className={cx(style.line, {
              [style.two]: _i == 1,
            })} key={_i}>
              {
                g.map((p, i) => (
                  <div className={cx(style.point, {
                    [style.main]: this.props.params.objectiveId === p.objectiveId || this.props.params.objectiveId == p.parentObjectiveId,
                    [style.current]: this.props.params.objectiveId === p.objectiveId,
                    [style.parent]: p.isParent,
                    [style['is-root']]: p.isRoot,
                  })} key={i}>
                  {
                    (p.isRoot && this.state.rootObjective) ? (
                      <Link
                        style={{
                          width: `${this.state.rootObjective.content.length * 16 < 200 ? 200 : this.state.rootObjective.content.length * 16}px`,
                          marginLeft: `-${ (this.state.rootObjective.content.length * 16 < 200 ? 200 : this.state.rootObjective.content.length * 16) / 2-10}px`,
                        }}
                        className={style['root-card']}
                        target="_blank"
                        to={`/okr/objectives/${p.objectiveId}?${util.body(this.props.location.query)}`}
                      ><span>{this.state.rootObjective.content}</span></Link>
                    ) : null
                  }
                    {
                      (this.state[p.objectiveId] || []).map((line, i) => (
                        <Motion
                          key={i}
                          defaultStyle={{ width: 0 }}
                          style={{ width: spring(line.length, {damping: 30, stiffness: 280}) }}
                        >
                          {
                            ({ width }) => (
                              <b
                                className={style['p-line']}
                                style={{
                                  width: `${width}px`,
                                  transform: `rotate(${line.angle}deg)`,
                                  WebkitTransfrom: `rotate(${line.angle}deg)`,
                                }}
                                key={i}
                              />
                            )
                          }
                        </Motion>
                      ))
                    }
                    <div
                      className={cx(style.p, {
                        [style.clickable]: this.props.params.objectiveId !== p.objectiveId && p.hasSubordinate,
                      })}
                      onClick={() => {
                        if (this.props.params.objectiveId === p.objectiveId) return;
                        if (p.hasSubordinate) {
                          const { pathname, query } = this.props.location;
                          this.context.router.push({
                            pathname: `objectives/${p.objectiveId}/bird-view`,
                            query,
                          });
                        }
                      }}
                      onMouseEnter={() => {
                        this.loadObjective(p.objectiveId)
                      }}
                      onMouseLeave={() => {
                        this.cancelObjective()
                      }}
                      ref={
                        el => {
                          if (el !== null && !el.load) {
                            // 如果有子节点
                            if (p.hasSubordinate) {
                              const rect = this.getRect(el);
                              if (!util.bus.hasListeners(`objective_bird:load_${p.objectiveId}`)) {
                                util.bus.on(`objective_bird:load_${p.objectiveId}`, (r) => {
                                  this.drawLine(rect, r, p.objectiveId);
                                });
                              }
                            }

                            // 如果有父节点
                            if (p.hasParent) {
                              const rect = this.getRect(el);
                              util.bus.emit(`objective_bird:load_${p.parentObjectiveId}`, rect);
                            }

                            el.load = true;
                          }
                        }
                      }
                    >
                      {
                        (this.state.loadObjective === p.objectiveId) ? (
                          <Card
                            isBird
                            className={style['p-card']}
                            isFetching={detail === null || detail.objectiveId != p.objectiveId}
                            query={this.props.location.query}
                            {...detail}
                          />
                        ) : null
                      }
                    </div>
                  </div>
                ))
              }
            </div>
          ))
        }
      </div>
    );
  }

  render() {
    const { pathname, query, } = this.props.location;
    const { objectiveId } = this.props.params;  
    return (
      <div className={style.root}>
        <ul className={nav}>
          <li>
            <Link
              activeClassName={navActive}
              to={`/objectives/${objectiveId}/relative-tree?${util.body(query)}`}
              label="卡片视图"
            />
          </li>
          <li>
            <Link
              activeClassName={navActive}
              to={`/objectives/${objectiveId}/bird-view?${util.body(query)}`}
              label="鸟瞰图"
            />
          </li>
        </ul>
        {
          this.renderView()
        }
      </div>
    );
  }
}
